﻿using Collab.Modules.Editing;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Linq;
using Collab.Services.Remote.Entities;
using System.Collections.Generic;
using System.Text;

namespace Collab.Test
{


    /// <summary>
    ///This is a test class for ChangeProcessorTest and is intended
    ///to contain all ChangeProcessorTest Unit Tests
    ///</summary>
    [TestClass()]
    public class ChangeProcessorTest
    {


        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion


        /// <summary>
        ///A test for InsertBufferUpdate
        ///</summary>
        [TestMethod()]
        [DeploymentItem("Collab.Modules.Editing.dll")]
        public void InsertBufferUpdateTest()
        {
        }

        /// <summary>
        ///A test for ProcessUpdate
        ///</summary>
        [TestMethod()]
        [DeploymentItem("Collab.Modules.Editing.dll")]
        public void ProcessUpdateTest()
        {
        }

        /// <summary>
        ///A test for RevisionIncrement
        ///</summary>
        [TestMethod()]
        public void RevisionIncrementTest()
        {
        }

        /// <summary>
        ///A test for SynchronizeUpdate
        ///</summary>
        [TestMethod()]
        [DeploymentItem("Collab.Modules.Editing.dll")]
        public void SynchronizeUpdateTest_SingleConflictingRevisionIsHandled()
        {
            Guid user1Guid = Guid.NewGuid();
            Guid user2Guid = Guid.NewGuid();

            BufferUpdate item1 = new BufferUpdate("doc1", user1Guid, 2, new List<Change>()
            {
                new Change(5,5,1,"a")
            });

            BufferUpdate item2 = new BufferUpdate("doc1", user2Guid, 2, new List<Change>()
            {
                new Change(6,6,1,"a")
            });


            ChangeProcessor processor = new ChangeProcessor();
            ChangeProcessor_Accessor target = new ChangeProcessor_Accessor();

            target.ProcessUpdate(item1);
            BufferUpdate actual = target.SynchronizeUpdate(item2);

            Assert.AreEqual(1, actual.Changes.Count());
            Assert.AreEqual(7, actual.Changes.First().OldStart);
            Assert.AreEqual(7, actual.Changes.First().OldEnd);
            Assert.AreEqual(3, actual.Revision);
        }



        /// <summary>
        ///A test for SynchronizeUpdate
        ///</summary>
        [TestMethod()]
        [DeploymentItem("Collab.Modules.Editing.dll")]
        public void SynchronizeUpdateTest_DualConflictingRevisionIsHandled()
        {
            Guid user1Guid = Guid.NewGuid();
            Guid user2Guid = Guid.NewGuid();

            BufferUpdate item1 = new BufferUpdate("doc1", user1Guid, 2, new List<Change>()
            {
                new Change(5,5,1,"a")
            });

            BufferUpdate item2 = new BufferUpdate("doc1", user1Guid, 3, new List<Change>()
            {
                new Change(6,6,1,"a")
            });

            BufferUpdate item3 = new BufferUpdate("doc1", user2Guid, 3, new List<Change>()
            {
                new Change(8,8,1,"b")
            });

            BufferUpdate item4 = new BufferUpdate("doc1", user2Guid, 4, new List<Change>()
            {
                new Change(8,8,1,"b")
            });

            ChangeProcessor processor = new ChangeProcessor();
            ChangeProcessor_Accessor target = new ChangeProcessor_Accessor();

            target.ProcessUpdate(item1);
            target.ProcessUpdate(item2);
            target.ProcessUpdate(item3);

            BufferUpdate actual;
            actual = target.SynchronizeUpdate(item4);
            Assert.AreEqual(1, actual.Changes.Count());
            Assert.AreEqual(9, actual.Changes.First().OldStart);
            Assert.AreEqual(9, actual.Changes.First().OldEnd);
            Assert.AreEqual(5, actual.Revision);
        }

        /// <summary>
        ///A test for SynchronizeUpdate
        ///</summary>
        [TestMethod()]
        [DeploymentItem("Collab.Modules.Editing.dll")]
        public void SynchronizeUpdateTest_DualConflictingRevisionIsHandled2()
        {
            Guid user1Guid = Guid.NewGuid();
            Guid user2Guid = Guid.NewGuid();

            BufferUpdate item1 = new BufferUpdate("doc1", user1Guid, 2, new List<Change>()
            {
                new Change(5,5,1,"a")
            });

            BufferUpdate item2 = new BufferUpdate("doc1", user1Guid, 3, new List<Change>()
            {
                new Change(6,6,1,"a")
            });

            BufferUpdate item3 = new BufferUpdate("doc1", user2Guid, 2, new List<Change>()
            {
                new Change(8,8,1,"b")
            });

            BufferUpdate item4 = new BufferUpdate("doc1", user2Guid, 3, new List<Change>()
            {
                new Change(8,8,1,"b")
            });




            ChangeProcessor processor = new ChangeProcessor();
            ChangeProcessor_Accessor target = new ChangeProcessor_Accessor();

            target.ProcessUpdate(item1);
            target.ProcessUpdate(item2);
            target.ProcessUpdate(item3);

            BufferUpdate actual;
            actual = target.SynchronizeUpdate(item4);
            Assert.AreEqual(1, actual.Changes.Count());
            Assert.AreEqual(10, actual.Changes.First().OldStart);
            Assert.AreEqual(10, actual.Changes.First().OldEnd);
            Assert.AreEqual(5, actual.Revision);
        }





        /// <summary>
        ///A test for SynchronizeUpdate
        ///</summary>
        [TestMethod()]
        [DeploymentItem("Collab.Modules.Editing.dll")]
        public void ProcessUpdateTest_DualConflictingRevisionIsHandled()
        {
            Guid user1Guid = Guid.NewGuid();
            Guid user2Guid = Guid.NewGuid();

            //string user1Text = "Alla barnen sitter ute i solen och äter glass!";
            //string user2Text = "Förutom Mikael för han är kass!";

            string user1Text = "Alla!";
            string user2Text = "För!";

            ChangeProcessor_Accessor target = new ChangeProcessor_Accessor();
            StringBuilder sb = new StringBuilder("  ");
            target.Subscribe(change =>
            {
                sb.Insert(change.Changes.First().OldStart, change.Changes.First().Text);
            });

            //U1 skriver "All"
            WriteText(user1Guid, 1, 1, "All", target);
            //U2 tar emot "A" och skriver sedan "Fö"
            WriteText(user2Guid, 3, 2, "Fö", target);
            //U1 tar emot "F" och skriver "a"
            WriteText(user1Guid, 4, 5, "a", target);
            //U2 tar emot "ll" och skriver "r!"
            WriteText(user2Guid, 7, 6, "r!", target);
            //U1 tar emot "ör" och skriver "!"
            WriteText(user1Guid, 5, 8, "!", target);

            string actual = sb.ToString();
            Assert.IsTrue(actual.Contains(user1Text));
            Assert.IsTrue(actual.Contains(user2Text));
            //Assert.AreEqual(1, actual.Changes.Count());
            //Assert.AreEqual(10, actual.Changes.First().OldStart);
            //Assert.AreEqual(10, actual.Changes.First().OldEnd);
            //Assert.AreEqual(5, actual.Revision);
        }

        /// <summary>
        ///A test for SynchronizeUpdate
        ///</summary>
        [TestMethod()]
        [DeploymentItem("Collab.Modules.Editing.dll")]
        public void SynchronizeUpdateTest_RealCase1()
        {
            Guid user1Guid = Guid.NewGuid();
            Guid user2Guid = Guid.NewGuid();

            BufferUpdate item1 = new BufferUpdate("doc1", user1Guid, 3, new List<Change>()
            {
                new Change(154,154,2,"\r\n")
            });
            BufferUpdate item2 = new BufferUpdate("doc1", user1Guid, 4, new List<Change>()
            {
                new Change(156,156,2,"\r\n")
            });
            BufferUpdate item3 = new BufferUpdate("doc1", user2Guid, 5, new List<Change>()
            {
                new Change(142,142,2,"\r\n")
            });
            BufferUpdate item4 = new BufferUpdate("doc1", user2Guid, 6, new List<Change>()
            {
                new Change(144,144,2,"\r\n")
            });
            BufferUpdate item5 = new BufferUpdate("doc1", user2Guid, 7, new List<Change>()
            {
                new Change(146,146,2,"\r\n")
            });
            BufferUpdate item6 = new BufferUpdate("doc1", user2Guid, 8, new List<Change>()
            {
                new Change(148,148,9,"        h")
            });
            BufferUpdate item7 = new BufferUpdate("doc1", user1Guid, 8, new List<Change>()
            {
                new Change(144,144,9,"        f")
            });
            BufferUpdate item8 = new BufferUpdate("doc1", user1Guid, 9, new List<Change>()
            {
                new Change(153,153,1,"d")
            });



            ChangeProcessor processor = new ChangeProcessor();
            ChangeProcessor_Accessor target = new ChangeProcessor_Accessor();

            target.ProcessUpdate(item1);
            target.ProcessUpdate(item2);
            target.ProcessUpdate(item3);
            target.ProcessUpdate(item4);
            target.ProcessUpdate(item5);
            target.ProcessUpdate(item6);
            target.ProcessUpdate(item7);
            //target.ProcessUpdate(item8);

            //string s = UnitTestBuilder.PrintCalculations();
            //Assert.AreEqual("aa", s);

            BufferUpdate actual;
            actual = target.SynchronizeUpdate(item8);
            Assert.AreEqual(1, actual.Changes.Count());
            Assert.AreEqual(153, actual.Changes.First().OldStart);
            Assert.AreEqual(153, actual.Changes.First().OldEnd);
            Assert.AreEqual(10, actual.Revision);
        }

        /// <summary>
        ///A test for SynchronizeUpdate
        ///</summary>
        [TestMethod()]
        [DeploymentItem("Collab.Modules.Editing.dll")]
        public void SynchronizeUpdateTest_RealCase2()
        {
            Guid user1Guid = Guid.NewGuid();
            Guid user2Guid = Guid.NewGuid();

            BufferUpdate item1 = new BufferUpdate("doc1", user1Guid, 3, new List<Change>()
            {
                new Change(154,154,2,"\r\n")
            });
            BufferUpdate item2 = new BufferUpdate("doc1", user1Guid, 4, new List<Change>()
            {
                new Change(156,156,2,"\r\n")
            });
            BufferUpdate item3 = new BufferUpdate("doc1", user2Guid, 5, new List<Change>()
            {
                new Change(142,142,2,"\r\n")
            });
            BufferUpdate item4 = new BufferUpdate("doc1", user2Guid, 6, new List<Change>()
            {
                new Change(144,144,2,"\r\n")
            });
            BufferUpdate item5 = new BufferUpdate("doc1", user2Guid, 7, new List<Change>()
            {
                new Change(146,146,2,"\r\n")
            });
            BufferUpdate item6 = new BufferUpdate("doc1", user2Guid, 8, new List<Change>()
            {
                new Change(148,148,9,"        h")
            });
            BufferUpdate item7 = new BufferUpdate("doc1", user1Guid, 8, new List<Change>()
            {
                new Change(144,144,9,"        f")
            });
            BufferUpdate item8 = new BufferUpdate("doc1", user1Guid, 9, new List<Change>()
            {
                new Change(153,153,1,"d")
            });
            BufferUpdate item9 = new BufferUpdate("doc1", user1Guid, 10, new List<Change>()
            {
                new Change(158,158,1,"c")
            });




            ChangeProcessor processor = new ChangeProcessor();
            ChangeProcessor_Accessor target = new ChangeProcessor_Accessor();

            target.ProcessUpdate(item1);
            target.ProcessUpdate(item2);
            target.ProcessUpdate(item3);
            target.ProcessUpdate(item4);
            target.ProcessUpdate(item5);
            target.ProcessUpdate(item6);
            target.ProcessUpdate(item7);
            target.ProcessUpdate(item8);

            //string s = UnitTestBuilder.PrintCalculations();
            //Assert.AreEqual("aa", s);

            BufferUpdate actual;
            actual = target.SynchronizeUpdate(item9);
            Assert.AreEqual(1, actual.Changes.Count());
            Assert.AreEqual(167, actual.Changes.First().OldStart);
            Assert.AreEqual(167, actual.Changes.First().OldEnd);
            Assert.AreEqual(11, actual.Revision);
        }


        /// <summary>
        ///A test for SynchronizeUpdate
        ///</summary>
        [TestMethod()]
        [DeploymentItem("Collab.Modules.Editing.dll")]
        public void ProcessUpdateTest_RuntimeGeneratedSequence1()
        {
            var list = new List<BufferUpdate>(){
             new BufferUpdate("doc1", new Guid("e7991949-65a5-4b0d-92d7-f75b1a2687d8"),3,  new List<Change>(){new Change(197,197,2,"\r\n")}),
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),4,  new List<Change>(){new Change(152,152,9,"        j")}), //HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),5,  new List<Change>(){new Change(161,161,1,"k")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),6,  new List<Change>(){new Change(162,162,1,"h")}),//HOST
             new BufferUpdate("doc1", new Guid("e7991949-65a5-4b0d-92d7-f75b1a2687d8"),4,  new List<Change>(){new Change(199,199,9,"        f")}), //CLIENT
             new BufferUpdate("doc1", new Guid("e7991949-65a5-4b0d-92d7-f75b1a2687d8"),8,  new List<Change>(){new Change(219,219,1,"d")}),
             new BufferUpdate("doc1", new Guid("e7991949-65a5-4b0d-92d7-f75b1a2687d8"),9,  new List<Change>(){new Change(220,220,1,"g")}),
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),10,  new List<Change>(){new Change(163,163,1,"j")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),11,  new List<Change>(){new Change(164,164,1,"k")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),12,  new List<Change>(){new Change(165,165,1,"j")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),13,  new List<Change>(){new Change(166,166,1,"k")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),14,  new List<Change>(){new Change(167,167,1,"h")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),15,  new List<Change>(){new Change(168,168,1,"j")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),16,  new List<Change>(){new Change(169,169,1,"k")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),17,  new List<Change>(){new Change(170,170,1,"h")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),18,  new List<Change>(){new Change(171,171,1,"j")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),19,  new List<Change>(){new Change(172,172,1,"h")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),20,  new List<Change>(){new Change(173,173,1,"k")}),//HOST
             new BufferUpdate("doc1", new Guid("e7991949-65a5-4b0d-92d7-f75b1a2687d8"),21,  new List<Change>(){new Change(232,232,1,"f")}),
             new BufferUpdate("doc1", new Guid("e7991949-65a5-4b0d-92d7-f75b1a2687d8"),22,  new List<Change>(){new Change(233,233,1,"d")}),
             new BufferUpdate("doc1", new Guid("e7991949-65a5-4b0d-92d7-f75b1a2687d8"),23,  new List<Change>(){new Change(234,234,1,"g")}),
             new BufferUpdate("doc1", new Guid("e7991949-65a5-4b0d-92d7-f75b1a2687d8"),24,  new List<Change>(){new Change(235,235,1,"d")}),
             new BufferUpdate("doc1", new Guid("e7991949-65a5-4b0d-92d7-f75b1a2687d8"),25,  new List<Change>(){new Change(236,236,1,"g")}),
             new BufferUpdate("doc1", new Guid("e7991949-65a5-4b0d-92d7-f75b1a2687d8"),26,  new List<Change>(){new Change(237,237,1,"f")}),
             new BufferUpdate("doc1", new Guid("e7991949-65a5-4b0d-92d7-f75b1a2687d8"),27,  new List<Change>(){new Change(238,238,1,"d")}),
             new BufferUpdate("doc1", new Guid("e7991949-65a5-4b0d-92d7-f75b1a2687d8"),28,  new List<Change>(){new Change(239,239,1,"f")}),
             new BufferUpdate("doc1", new Guid("e7991949-65a5-4b0d-92d7-f75b1a2687d8"),29,  new List<Change>(){new Change(240,240,1,"g")}),
             new BufferUpdate("doc1", new Guid("e7991949-65a5-4b0d-92d7-f75b1a2687d8"),30,  new List<Change>(){new Change(241,241,1,"d")}),
             new BufferUpdate("doc1", new Guid("e7991949-65a5-4b0d-92d7-f75b1a2687d8"),31,  new List<Change>(){new Change(242,242,1,"f")}),
             new BufferUpdate("doc1", new Guid("e7991949-65a5-4b0d-92d7-f75b1a2687d8"),32,  new List<Change>(){new Change(243,243,1,"g")}),
             new BufferUpdate("doc1", new Guid("e7991949-65a5-4b0d-92d7-f75b1a2687d8"),33,  new List<Change>(){new Change(244,244,1,"d")}),
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),34,  new List<Change>(){new Change(174,174,1,"h")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),35,  new List<Change>(){new Change(175,175,1,"j")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),36,  new List<Change>(){new Change(176,176,1,"k")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),37,  new List<Change>(){new Change(177,177,1,"h")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),38,  new List<Change>(){new Change(178,178,1,"j")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),39,  new List<Change>(){new Change(179,179,1,"k")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),40,  new List<Change>(){new Change(180,180,1,"h")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),41,  new List<Change>(){new Change(181,181,1,"j")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),42,  new List<Change>(){new Change(182,182,1,"k")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),43,  new List<Change>(){new Change(183,183,1,"h")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),44,  new List<Change>(){new Change(184,184,1,"j")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),45,  new List<Change>(){new Change(185,185,1,"k")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),46,  new List<Change>(){new Change(186,186,1,"j")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),47,  new List<Change>(){new Change(187,187,1,"h")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),48,  new List<Change>(){new Change(188,188,1,"k")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),49,  new List<Change>(){new Change(189,189,1,"j")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),50,  new List<Change>(){new Change(190,190,1,"h")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),51,  new List<Change>(){new Change(191,191,1,"k")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),52,  new List<Change>(){new Change(192,192,1,"h")}),//HOST
             new BufferUpdate("doc1", new Guid("e7991949-65a5-4b0d-92d7-f75b1a2687d8"),53,  new List<Change>(){new Change(264,264,1,"r")}),
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),54,  new List<Change>(){new Change(193,193,1,"u")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),55,  new List<Change>(){new Change(194,194,1,"i")}),//HOST
             new BufferUpdate("doc1", new Guid("e7991949-65a5-4b0d-92d7-f75b1a2687d8"),54,  new List<Change>(){new Change(265,265,1,"s")}),
             new BufferUpdate("doc1", new Guid("e7991949-65a5-4b0d-92d7-f75b1a2687d8"),56,  new List<Change>(){new Change(267,267,1,"d")}),
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),58,  new List<Change>(){new Change(195,195,1,"u")}),//HOST
             new BufferUpdate("doc1", new Guid("e7991949-65a5-4b0d-92d7-f75b1a2687d8"),59,  new List<Change>(){new Change(270,270,1,"f")}),
             new BufferUpdate("doc1", new Guid("e7991949-65a5-4b0d-92d7-f75b1a2687d8"),60,  new List<Change>(){new Change(271,271,1,"g")}),
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),61,  new List<Change>(){new Change(196,196,1,"u")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),62,  new List<Change>(){new Change(197,197,1,"h")}),//HOST
             new BufferUpdate("doc1", new Guid("e7991949-65a5-4b0d-92d7-f75b1a2687d8"),61,  new List<Change>(){new Change(272,272,1,"d")}),
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),64,  new List<Change>(){new Change(198,198,1,"u")}),//HOST
             new BufferUpdate("doc1", new Guid("e7991949-65a5-4b0d-92d7-f75b1a2687d8"),64,  new List<Change>(){new Change(275,275,1,"r")}),
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),66,  new List<Change>(){new Change(199,199,1,"h")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),67,  new List<Change>(){new Change(200,200,1,"h")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),68,  new List<Change>(){new Change(201,201,1,"u")}),//HOST
             new BufferUpdate("doc1", new Guid("e7991949-65a5-4b0d-92d7-f75b1a2687d8"),69,  new List<Change>(){new Change(280,280,1,"g")}),
             new BufferUpdate("doc1", new Guid("e7991949-65a5-4b0d-92d7-f75b1a2687d8"),70,  new List<Change>(){new Change(281,281,1,"s")}),
             new BufferUpdate("doc1", new Guid("e7991949-65a5-4b0d-92d7-f75b1a2687d8"),71,  new List<Change>(){new Change(282,282,1,"d")}),
             new BufferUpdate("doc1", new Guid("e7991949-65a5-4b0d-92d7-f75b1a2687d8"),72,  new List<Change>(){new Change(283,283,1,"f")}),
             new BufferUpdate("doc1", new Guid("e7991949-65a5-4b0d-92d7-f75b1a2687d8"),73,  new List<Change>(){new Change(284,284,1,"g")}),
             new BufferUpdate("doc1", new Guid("e7991949-65a5-4b0d-92d7-f75b1a2687d8"),74,  new List<Change>(){new Change(285,285,1,"d")}),
             new BufferUpdate("doc1", new Guid("e7991949-65a5-4b0d-92d7-f75b1a2687d8"),75,  new List<Change>(){new Change(286,286,1,"f")}),
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),76,  new List<Change>(){new Change(202,202,1,"h")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),77,  new List<Change>(){new Change(203,203,1,"o")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),78,  new List<Change>(){new Change(204,204,1,"h")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),79,  new List<Change>(){new Change(205,205,1,"k")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),80,  new List<Change>(){new Change(206,206,1,"j")}),//HOST
             new BufferUpdate("doc1", new Guid("e7991949-65a5-4b0d-92d7-f75b1a2687d8"),79,  new List<Change>(){new Change(290,290,1,"d")}), //CLIENT FAIL
             new BufferUpdate("doc1", new Guid("e7991949-65a5-4b0d-92d7-f75b1a2687d8"),82,  new List<Change>(){new Change(293,293,1,"f")}), //CLIENT FAIL
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),82,  new List<Change>(){new Change(207,207,1,"l")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),84,  new List<Change>(){new Change(208,208,1,"k")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),85,  new List<Change>(){new Change(209,209,1,"j")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),86,  new List<Change>(){new Change(210,210,1,"l")}),//HOST
             new BufferUpdate("doc1", new Guid("e7991949-65a5-4b0d-92d7-f75b1a2687d8"),87,  new List<Change>(){new Change(298,298,1,"g")}),
             new BufferUpdate("doc1", new Guid("e7991949-65a5-4b0d-92d7-f75b1a2687d8"),88,  new List<Change>(){new Change(299,299,1,"f")}),
             new BufferUpdate("doc1", new Guid("e7991949-65a5-4b0d-92d7-f75b1a2687d8"),89,  new List<Change>(){new Change(300,300,1,"d")}),
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),90,  new List<Change>(){new Change(211,211,1,"j")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),91,  new List<Change>(){new Change(212,212,1,"k")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),92,  new List<Change>(){new Change(213,213,1,"l")}),//HOST
             new BufferUpdate("doc1", new Guid("e7991949-65a5-4b0d-92d7-f75b1a2687d8"),90,  new List<Change>(){new Change(301,301,1,"g")}),
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),94,  new List<Change>(){new Change(214,214,1,"k")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),95,  new List<Change>(){new Change(215,215,1,"j")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),96,  new List<Change>(){new Change(216,216,1,"l")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),97,  new List<Change>(){new Change(217,217,1,"k")}),//HOST
             new BufferUpdate("doc1", new Guid("e7991949-65a5-4b0d-92d7-f75b1a2687d8"),97,  new List<Change>(){new Change(308,308,1,"d")}),
             new BufferUpdate("doc1", new Guid("e7991949-65a5-4b0d-92d7-f75b1a2687d8"),99,  new List<Change>(){new Change(310,310,1,"g")}),
             new BufferUpdate("doc1", new Guid("e7991949-65a5-4b0d-92d7-f75b1a2687d8"),100,  new List<Change>(){new Change(311,311,1,"f")}),
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),101,  new List<Change>(){new Change(218,218,1,"j")}),//HOST
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),102,  new List<Change>(){new Change(219,219,1,"l")}),//HOST
             new BufferUpdate("doc1", new Guid("e7991949-65a5-4b0d-92d7-f75b1a2687d8"),101,  new List<Change>(){new Change(312,312,1,"d")}),
             new BufferUpdate("doc1", new Guid("10e64da0-721e-4da4-9596-16264f234e15"),104,  new List<Change>(){new Change(315,315,2,"\r\n")}),//HOST
           };

            ChangeProcessor_Accessor target = new ChangeProcessor_Accessor();
            StringBuilder sb = new StringBuilder("using System;\r\nusing System.Collections.Generic;\r\nusing System.Linq;\r\nusing System.Text;\r\n\r\nnamespace ClassLibrary2\r\n{\r\n    public class Class1\r\n    {\r\n\r\n        public int MyProperty { get; set; }\r\n    }\r\n}");
            target.Subscribe(change =>
            {
                sb.Remove(change.Changes.First().OldStart, change.Changes.First().OldStart -change.Changes.First().OldStart);
                sb.Insert(change.Changes.First().OldStart, change.Changes.First().Text);
            });

            list.Run(update => target.ProcessUpdate(update));

            string actual = sb.ToString();
            string expected = "using System;\r\nusing System.Collections.Generic;\r\nusing System.Linq;\r\nusing System.Text;\r\n\r\nnamespace ClassLibrary2\r\n{\r\n    public class Class1\r\n    {\r\n        jkhjkjkhjkhjhkhjkhjkhjkhjkjhkjhkhuiuuhuhhuhohkjlkjljklkjlkjl\r\n        public int MyProperty { get; set; }\r\n        fdgfdgdgfdfgdfgdrsdfgdrgsdfgdfdfgfdgdgfd\r\n\r\n    }\r\n}";
            //Assert.IsTrue(actual.Contains(user1Text));
            //Assert.IsTrue(actual.Contains(user2Text));
            //Assert.AreEqual(1, actual.Changes.Count());
            //Assert.AreEqual(10, actual.Changes.First().OldStart);
            //Assert.AreEqual(10, actual.Changes.First().OldEnd);
            //Assert.AreEqual(5, actual.Revision);
            Assert.AreEqual(expected, actual);
            ////U1 skriver "All"
            //WriteText(user1Guid, 1, 1, "All", target);
            ////U2 tar emot "A" och skriver sedan "Fö"
            //WriteText(user2Guid, 3, 2, "Fö", target);
            ////U1 tar emot "F" och skriver "a"
            //WriteText(user1Guid, 4, 5, "a", target);
            ////U2 tar emot "ll" och skriver "r!"
            //WriteText(user2Guid, 7, 6, "r!", target);
            ////U1 tar emot "ör" och skriver "!"
            //WriteText(user1Guid, 5, 8, "!", target);

            
        }

        private void WriteText(Guid guid, int startIndex, int revision, string text, ChangeProcessor_Accessor target)
        {
            var arr = text.ToCharArray();
            for (int i = 0; i < arr.Length; i++)
            {
                BufferUpdate item = new BufferUpdate("doc1", guid, revision + i, new List<Change>()
                {
                    new Change(startIndex + i,startIndex + i,1,arr[i].ToString())
                });
                target.ProcessUpdate(item);
            }
        }

        /// <summary>
        ///A test for SynchronizeUpdate
        ///</summary>
        [TestMethod()]
        [DeploymentItem("Collab.Modules.Editing.dll")]
        public void SynchronizeUpdateTest_LaterChangesAreSkipped()
        {
            Guid user1Guid = Guid.NewGuid();
            Guid user2Guid = Guid.NewGuid();

            BufferUpdate item1 = new BufferUpdate("doc1", user1Guid, 2, new List<Change>()
            {
                new Change(5,5,1,"a")
            });

            BufferUpdate item2 = new BufferUpdate("doc1", user1Guid, 3, new List<Change>()
            {
                new Change(8,8,1,"a")
            });

            BufferUpdate item3 = new BufferUpdate("doc1", user2Guid, 2, new List<Change>()
            {
                new Change(6,6,1,"b")
            });


            ChangeProcessor processor = new ChangeProcessor();
            ChangeProcessor_Accessor target = new ChangeProcessor_Accessor();

            target.ProcessUpdate(item1);
            target.ProcessUpdate(item2);

            BufferUpdate actual;
            actual = target.SynchronizeUpdate(item3);
            Assert.AreEqual(1, actual.Changes.Count());
            Assert.AreEqual(7, actual.Changes.First().OldStart);
            Assert.AreEqual(7, actual.Changes.First().OldEnd);
            Assert.AreEqual(4, actual.Revision);
        }

        /// <summary>
        ///A test for SynchronizeUpdate
        ///</summary>
        [TestMethod()]
        [DeploymentItem("Collab.Modules.Editing.dll")]
        public void SynchronizeUpdateTest_TripleUsersSingleUnSyncedWorks()
        {
            Guid user1Guid = Guid.NewGuid();
            Guid user2Guid = Guid.NewGuid();
            Guid user3Guid = Guid.NewGuid();


            BufferUpdate item1 = new BufferUpdate("doc1", user1Guid, 2, new List<Change>()
            {
                new Change(5,5,1,"a")
            });

            BufferUpdate item2 = new BufferUpdate("doc1", user2Guid, 3, new List<Change>()
            {
                new Change(6,6,1,"a")
            });

            BufferUpdate item3 = new BufferUpdate("doc1", user3Guid, 3, new List<Change>()
            {
                new Change(8,8,1,"b")
            });


            ChangeProcessor processor = new ChangeProcessor();
            ChangeProcessor_Accessor target = new ChangeProcessor_Accessor();

            target.ProcessUpdate(item1);
            target.ProcessUpdate(item2);

            BufferUpdate actual;
            actual = target.SynchronizeUpdate(item3);
            Assert.AreEqual(1, actual.Changes.Count());
            Assert.AreEqual(9, actual.Changes.First().OldStart);
            Assert.AreEqual(9, actual.Changes.First().OldEnd);
            Assert.AreEqual(4, actual.Revision);
        }





        /// <summary>
        ///A test for SynchronizeUpdate
        ///</summary>
        [TestMethod()]
        [DeploymentItem("Collab.Modules.Editing.dll")]
        public void SynchronizeUpdateTest_TripleUsersDualUnSyncedWorks()
        {
            Guid user1Guid = Guid.NewGuid();
            Guid user2Guid = Guid.NewGuid();
            Guid user3Guid = Guid.NewGuid();


            BufferUpdate item1 = new BufferUpdate("doc1", user1Guid, 2, new List<Change>()
            {
                new Change(5,5,1,"a")
            });

            BufferUpdate item2 = new BufferUpdate("doc1", user2Guid, 2, new List<Change>()
            {
                new Change(6,6,1,"a")
            });

            BufferUpdate item3 = new BufferUpdate("doc1", user3Guid, 2, new List<Change>()
            {
                new Change(8,8,1,"b")
            });


            ChangeProcessor processor = new ChangeProcessor();
            ChangeProcessor_Accessor target = new ChangeProcessor_Accessor();

            target.ProcessUpdate(item1);
            target.ProcessUpdate(item2);

            BufferUpdate actual;
            actual = target.SynchronizeUpdate(item3);
            Assert.AreEqual(1, actual.Changes.Count());
            Assert.AreEqual(10, actual.Changes.First().OldStart);
            Assert.AreEqual(10, actual.Changes.First().OldEnd);
            Assert.AreEqual(4, actual.Revision);
        }


        /// <summary>
        ///A test for SynchronizeUpdate
        ///</summary>
        [TestMethod()]
        [DeploymentItem("Collab.Modules.Editing.dll")]
        public void SynchronizeUpdateTest_TripleUsersDualUnSyncedComplexWorks()
        {
            Guid user1Guid = Guid.NewGuid();
            Guid user2Guid = Guid.NewGuid();
            Guid user3Guid = Guid.NewGuid();


            BufferUpdate item1 = new BufferUpdate("doc1", user1Guid, 2, new List<Change>()
            {
                new Change(5,5,1,"a")
            });

            BufferUpdate item2 = new BufferUpdate("doc1", user1Guid, 3, new List<Change>()
            {
                new Change(6,6,1,"a")
            });

            BufferUpdate item3 = new BufferUpdate("doc1", user2Guid, 2, new List<Change>()
            {
                new Change(8,8,1,"b")
            });

            BufferUpdate item4 = new BufferUpdate("doc1", user2Guid, 3, new List<Change>()
            {
                new Change(9,9,1,"b")
            });

            BufferUpdate item5 = new BufferUpdate("doc1", user3Guid, 2, new List<Change>()
            {
                new Change(10,10,1,"b")
            });

            BufferUpdate item6 = new BufferUpdate("doc1", user3Guid, 3, new List<Change>()
            {
                new Change(11,11,1,"b")
            });

            ChangeProcessor processor = new ChangeProcessor();
            ChangeProcessor_Accessor target = new ChangeProcessor_Accessor();

            target.ProcessUpdate(item1);
            target.ProcessUpdate(item2);
            target.ProcessUpdate(item3);
            target.ProcessUpdate(item5);
            target.ProcessUpdate(item4);

            BufferUpdate actual;
            actual = target.SynchronizeUpdate(item6);
            Assert.AreEqual(1, actual.Changes.Count());
            Assert.AreEqual(15, actual.Changes.First().OldStart);
            Assert.AreEqual(15, actual.Changes.First().OldEnd);
            Assert.AreEqual(7, actual.Revision);
        }
    }
}
